package yagwl.server.demo;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import yagwl.service.demo.CartEntity;
import yagwl.service.demo.CommerceService;
import yagwl.service.demo.CommerceServiceImpl;
import yagwl.service.demo.ProductCategoryEntity;
import yagwl.service.fnd.flex.ConfigService;
import yagwl.service.util.svc.CacheService;
import yagwl.service.util.svc.Context;
import flexjson.JSONSerializer;

@SuppressWarnings("serial")
public class RestApiServlet extends HttpServlet {

  private static final Logger log = Logger.getLogger(RestApiServlet.class
      .getName());
  private HttpServletRequest request;
  private HttpServletResponse response;
  private PrintWriter out;
  private JSONSerializer serializer = new JSONSerializer().prettyPrint(true)
      .exclude("*.class");
  private CommerceService svc = CommerceServiceImpl.getInstance();

  private enum Api {
    catalog, category, addToCart, removeFromCart, cart, submitOrder, login, invalidateCache
  }

  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    log.info("Entering");
    this.request = request;
    this.response = response;
    out = response.getWriter();

    String api = request.getParameter("api");
    if (Api.catalog.toString().equals(api))
      catalog();
    else if (Api.addToCart.toString().equals(api))
      addToCart();
    else if (Api.removeFromCart.toString().equals(api))
      removeFromCart();
    else if (Api.cart.toString().equals(api))
      cart();
    else if (Api.login.toString().equals(api))
      login();
    else if (Api.submitOrder.toString().equals(api))
      submitOrder();
    else if (Api.invalidateCache.toString().equals(api))
      invalidateCache();
    else
      help();
  }

  private void invalidateCache() {
    CacheService cache = CacheService.getInstance();
    cache.invalidateAll();
  }

  private void help() {
    out.println("All API signatures: http://app.moebli.com/api<br>");
    out
        .println("User login: http://app.moebli.com/api?api=login&username=&lt;uid>&password=&lt;pwd><br>");
    out
        .println("Get product catalog: http://app.moebli.com/api?api=catalog<br>");
    out
        .println("Add product to cart: http://app.moebli.com/api?api=addToCart&productId=&lt;9999><br>");
    out
        .println("Remove from cart: http://app.moebli.com/api?api=removeFromCart&productId=&lt;9999><br>");
    out.println("Get cart: http://app.moebli.com/api?api=cart<br>");
    out
        .println("Submit order (wip): http://app.moebli.com/api?api=submitOrder<br>");
  }

  private void catalog() {
    log.info("Entering");
    ProductCategoryEntity cat = svc.getCategoryTree();
    serialize(cat);
  }

  private void login() {
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    if (username == null || password == null) {
      log.info("UnAuthenticated");
      return;
    }
    Context ctx = Context.getCurrentInstance();
    ctx.setUserId(username);
    String cookieName = ConfigService.getInstance()
        .getSessionCookieName();
    String sessionToken = ctx.getSessionToken();
    log.info("Setting cookie: " + sessionToken);
    Cookie cookie = new Cookie(cookieName, sessionToken);
    cookie.setMaxAge(60 * 60 * 24 * 7);
    response.addCookie(cookie);
    log.info("Authenticated");
  }

  private void addToCart() {
    log.info("Entering");
    String productId = request.getParameter("productId");
    int quantity = 1;
    try {
      quantity = Integer.parseInt(request.getParameter("quantity"));
    } catch (Exception e) {
    }
    if (productId == null || productId.trim().length() == 0) {
      // TODO P3 return error
      return;
    }
    CartEntity cart = svc.addToCart(productId, quantity);
    serialize(cart);
  }

  private void removeFromCart() {
    String productId = request.getParameter("productId");
    if (productId == null || productId.trim().length() == 0) {
      return;
    }
    CartEntity cart = svc.removeFromCart(productId);
    serialize(cart);
  }

  private void cart() {
    CartEntity cart = svc.getCart();
    serialize(cart);
  }

  private void submitOrder() {
    // TODO P4 submit order to be implemented
  }

  private void serialize(ProductCategoryEntity cat) {
    serializer.exclude("*.productIds");
    out.println(serializer.deepSerialize(cat));
  }

  private void serialize(CartEntity cart) {
    serializer.exclude("cartLineIds", "userId");
    out.println(serializer.deepSerialize(cart));
  }

}